home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
haeberli
/
libgutil
/
geom.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
11KB
|
496 lines
/*
* Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*/
/*
* geom -
* A software geometry package for computer graphics.
*
* David J. Brown - 1983
*/
#include "values.h"
#include "math.h"
#include "stdio.h"
#define STACKSIZE 20
static float Vm_Stack[STACKSIZE][4][4];
static int SP = -1;
static float Vm[4][4]; /* Viewing matrix */
static float Vsx, Vsy, Vcx, Vcy; /* Viewport parameters */
/*
* initmatstack -
* Initialize the matrix stack and the viewport
*/
i_initmatstack()
{
i_initmatrix();
i_initviewport();
}
/*
* initviewport -
* Initialize the viewport
*/
i_initviewport()
{
Vsx = 1.0;
Vsy = 1.0;
Vcx = 0.0;
Vcy = 0.0;
}
/*
* initmatrix -
* Set the matrix to the identity
*/
i_initmatrix()
{
i_initmat(Vm);
}
i_initmat(matrix)
float *matrix;
{
*matrix++ = 1.0; /* row 1 */
*matrix++ = 0.0;
*matrix++ = 0.0;
*matrix++ = 0.0;
*matrix++ = 0.0; /* row 2 */
*matrix++ = 1.0;
*matrix++ = 0.0;
*matrix++ = 0.0;
*matrix++ = 0.0; /* row 3 */
*matrix++ = 0.0;
*matrix++ = 1.0;
*matrix++ = 0.0;
*matrix++ = 0.0; /* row 4 */
*matrix++ = 0.0;
*matrix++ = 0.0;
*matrix++ = 1.0;
}
/*
* viewport -
* Set the current viewport
*/
i_viewport( l, r, b, t)
float l, r, b, t;
{
Vsx = r-l;
Vsy = t-b;
Vcx = (r+l)/2.0;
Vcy = (t+b)/2.0;
}
/*
* pushmatrix -
* Push the current matrix onto the stack
*/
i_pushmatrix()
{
int row, col;
if (SP == STACKSIZE-1)
puts("Stack is Full");
else {
SP++;
for(row=0 ; row<4 ; row++)
for(col=0 ; col<4 ; col++)
Vm_Stack[SP][row][col] = Vm[row][col];
}
}
/*
* popmatrix -
* Pop the current matrix off the stack
*/
i_popmatrix()
{
int row, col;
if (SP == -1)
puts("Stack is Empty");
else {
for(row=0 ; row<4 ; row++)
for(col=0 ; col<4 ; col++)
Vm[row][col] = Vm_Stack[SP][row][col];
SP--;
}
}
/*
* scale -
* Scale the current matrix
*/
i_scale(Sx, Sy, Sz)
float Sx, Sy, Sz;
{
int i;
for(i=0 ; i<4 ; i++)
Vm[0][i] *= Sx;
for(i=0 ; i<4 ; i++)
Vm[1][i] *= Sy;
for(i=0 ; i<4 ; i++)
Vm[2][i] *= Sz;
}
/*
* loadmatrix -
* Load the current matrix
*/
i_loadmatrix( m )
float m[4][4];
{
int i, j;
for(i=0; i<4; i++)
for(j=0; j<4; j++)
Vm[i][j] = m[i][j];
}
/*
* translate -
* Translate the current matrix
*/
i_translate(Tx, Ty, Tz)
float Tx, Ty, Tz;
{
Vm[3][0] += (Tx*Vm[0][0] + Ty*Vm[1][0] + Tz*Vm[2][0]);
Vm[3][1] += (Tx*Vm[0][1] + Ty*Vm[1][1] + Tz*Vm[2][1]);
Vm[3][2] += (Tx*Vm[0][2] + Ty*Vm[1][2] + Tz*Vm[2][2]);
}
/*
* rotate -
* Rotate about an axis
*/
i_rotate(angle, axis)
float angle;
char axis;
{
int row,col;
float temp[4];
float cosine, sine;
for(col=0; col<4 ; col++) /* init temp to zero matrix */
temp[col] = 0;
angle = angle*(3.1415926535/180.0);
cosine = cos(angle);
sine = sin(angle);
switch(axis){
case 'x':
case 'X':
for(col=0 ; col<4 ; col++)
temp[col] = cosine*Vm[1][col] + sine*Vm[2][col];
for(col=0 ; col<4 ; col++) {
Vm[2][col] = - sine*Vm[1][col] + cosine*Vm[2][col];
Vm[1][col] = temp[col];
}
break;
case 'y':
case 'Y':
for(col=0 ; col<4 ; col++)
temp[col] = cosine*Vm[0][col] - sine*Vm[2][col];
for(col=0 ; col<4 ; col++) {
Vm[2][col] = sine*Vm[0][col] + cosine*Vm[2][col];
Vm[0][col] = temp[col];
}
break;
case 'z':
case 'Z':
for(col=0 ; col<4 ; col++)
temp[col] = cosine*Vm[0][col] + sine*Vm[1][col];
for(col=0 ; col<4 ; col++) {
Vm[1][col] = - sine*Vm[0][col] + cosine*Vm[1][col];
Vm[0][col] = temp[col];
}
break;
}
}
/*
* multmatrix -
* Premultiply the current matrix
*/
i_multmatrix(icand)
float icand[4][4];
{
int row, col;
float temp[4][4];
for(row=0 ; row<4 ; row++)
for(col=0 ; col<4 ; col++)
temp[row][col] = icand[row][0] * Vm[0][col]
+ icand[row][1] * Vm[1][col]
+ icand[row][2] * Vm[2][col]
+ icand[row][3] * Vm[3][col];
for(row=0 ; row<16 ; row++)
*(Vm[0]+row) = *(temp[0]+row);
}
/*
* transform -
* Transform the coordinates using the current matrix.
*/
i_transform(x,y,z,tx,ty,tz)
float x,y,z;
float *tx,*ty,*tz;
{
int col;
float Vc[4];
for(col=0 ; col<3 ; col++)
Vc[col] = x*Vm[0][col] + y*Vm[1][col] + z*Vm[2][col] + Vm[3][col];
*tx = Vsx*Vc[0]+Vcx;
*ty = Vsy*Vc[1]+Vcy;
*tz = Vc[2];
}
/*
* transform4 -
* Transform the coordinates using the current matrix.
*/
i_transform4(x,y,z,w,tx,ty,tz,tw)
float x,y,z,w;
float *tx,*ty,*tz,*tw;
{
int col;
float Vc[4];
for(col=0 ; col<4 ; col++)
Vc[col] = x*Vm[0][col] + y*Vm[1][col] + z*Vm[2][col] + w*Vm[3][col];
*tx = Vsx*Vc[0]+Vcx;
*ty = Vsy*Vc[1]+Vcy;
*tz = Vc[2];
*tw = Vc[3];
}
/*
* polarview -
* Concatenate a polarview matrix
*
*/
i_polarview(dist, azimuth, incidence, twist)
float dist;
float azimuth, incidence, twist;
{
i_translate(0.0, 0.0, -dist);
i_rotate(-twist,'z');
i_rotate(-incidence,'x');
i_rotate(-azimuth,'z');
}
/*
* lookat -
* Concatenate a lookat matrix
*/
i_lookat(vx, vy, vz, px, py, pz, twist)
float vx, vy, vz, px, py, pz;
float twist;
{
float sine, cosine, hyp, hyp1, dx, dy, dz;
float mat[4][4];
i_rotate(-twist,'z');
dx = px - vx;
dy = py - vy;
dz = pz - vz;
hyp = dx * dx + dz * dz; /* hyp squared */
hyp1 = sqrt(dy*dy + hyp);
hyp = sqrt(hyp); /* the real hyp */
i_initmat(mat);
if (hyp1 != 0.0) { /* rotate X */
sine = -dy / hyp1;
cosine = hyp /hyp1;
} else {
sine = 0;
cosine = 1.0;
}
mat[1][1] = cosine;
mat[1][2] = sine;
mat[2][1] = -sine;
mat[2][2] = cosine;
i_multmatrix(mat);
mat[1][1] = mat[2][2] = 1.0; /* be careful here to reinit */
mat[1][2] = mat[2][1] = 0.0; /* those modified by the last */
/* paragraph */
if (hyp != 0.0) { /* rotate Y */
sine = dx / hyp;
cosine = -dz / hyp;
} else {
sine = 0;
cosine = 1.0;
}
mat[0][0] = cosine;
mat[0][2] = -sine;
mat[2][0] = sine;
mat[2][2] = cosine;
i_multmatrix(mat);
i_translate(-vx,-vy,-vz); /* translate viewpoint to origin */
}
/*
* window -
* Set up a 3d PERSPECTIVE window. This loads the matrix onto
* the stack destroying the current transformation.
*/
i_window(left, right, bottom, top, near, far)
float left, right, bottom, top, near, far;
{
float Xdelta, Ydelta, Zdelta;
float mat[4][4];
Xdelta = right - left;
Ydelta = top - bottom;
Zdelta = far - near;
if (Xdelta == 0.0 || Ydelta == 0.0 || Zdelta == 0.0) {
fprintf(stderr,"window: window width, height, or depth is 0.0\n");
return;
}
mat[0][0] = near * 2.0/Xdelta;
mat[1][1] = near * 2.0/Ydelta;
mat[2][0] = (right + left)/Xdelta; /* note: negate Z */
mat[2][1] = (top + bottom)/Ydelta;
mat[2][2] = -(far + near)/Zdelta;
mat[2][3] = -1.0;
mat[3][2] = -2.0 * near * far / Zdelta;
mat[0][1] = mat[0][2] = mat[0][3] =
mat[1][0] = mat[1][2] = mat[1][3] =
mat[3][0] = mat[3][1] = mat[3][3] = 0.0;
i_loadmatrix(mat);
}
/*
* perspective -
* Set up a perspective window. This loads the matrix onto
* the stack destroying the current transformation.
*/
i_perspective(fovy,aspect,near,far)
float fovy, aspect, near, far;
{
float Zdelta, cotangent;
float matrix[4][4];
if (fovy <= 0.1 || fovy > 180.0) {
fprintf(stderr,"perspective: fovy is out of range [0.1,180.0]\n");
return;
}
Zdelta = far-near;
if (aspect == 0.0 || Zdelta == 0.0) {
fprintf(stderr,"perspective: window width or depth is 0.0\n");
return;
}
fovy = ((fovy*M_PI)/180.0);
fovy /= 2; /* take half the angle*/
i_initmat(matrix);
cotangent = cos(fovy) / sin(fovy);
matrix[0][0] = cotangent / aspect;
matrix[1][1] = cotangent;
matrix[2][2] = -(far+near)/Zdelta;
matrix[2][3] = -1.0;
matrix[3][2] = -(2.0*far*near)/Zdelta;
matrix[3][3] = 0.0;
i_loadmatrix(matrix);
}
/*
* ortho -
* Set up a 3d window. This loads the matrix onto the stack
* destroying the current transformation.
*/
i_ortho(left, right, bottom, top, near, far)
float left, right, bottom, top, near, far;
{
float Xdelta, Ydelta, Zdelta;
float matrix[4][4];
Xdelta = right - left;
Ydelta = top - bottom;
Zdelta = far - near;
if (Xdelta == 0.0 || Ydelta == 0.0 || Zdelta == 0.0) {
fprintf(stderr,"ortho: window width, height, or depth is 0.0\n");
return;
}
i_initmat(matrix);
matrix[0][0] = 2.0/Xdelta;
matrix[3][0] = -(right + left)/Xdelta;
matrix[1][1] = 2.0/Ydelta;
matrix[3][1] = -(top + bottom)/Ydelta;
matrix[2][2] = -2.0/Zdelta; /* note: negate Z */
matrix[3][2] = -(far + near)/Zdelta;
i_loadmatrix(matrix);
}
/*
* ortho2 -
* Set up a 2d window. This loads the matrix onto the stack
* destroying the current transformation. Note that the new
* transformation leaves Z negated.
*/
i_ortho2(left, right, bottom, top)
float left, right, bottom, top;
{
float Xdelta, Ydelta;
float matrix[4][4];
Xdelta = right - left;
Ydelta = top - bottom;
if (Xdelta == 0.0 || Ydelta == 0.0) {
fprintf(stderr,"ortho2: window width or height is 0.0\n");
return;
}
i_initmat(matrix);
matrix[0][0] = 2.0/Xdelta;
matrix[3][0] = -(right + left)/Xdelta;
matrix[1][1] = 2.0/Ydelta;
matrix[3][1] = -(top + bottom)/Ydelta;
matrix[2][2] = -1.0;
i_loadmatrix(matrix);
}
float disttobezier(x, y, v1, v2, v3, v4)
float x, y;
float v1[2], v2[2], v3[2], v4[2];
{
float vmin, vv;
float x1[2], x2[2], x3[2], x4[2], p[2], t;
float t3, t2, t1, t0;
x1[0] = v1[0]; x1[1] = v1[1];
x2[0] = v2[0]; x2[1] = v2[1];
x3[0] = v3[0]; x3[1] = v3[1];
x4[0] = v4[0]; x4[1] = v4[1];
vmin = 1.0e30;
for (t = 0.0; t <= 1.0001; t += .001) {
t3 = t*t*t;
t2 = 3.0*t*t*(1.0-t);
t1 = 3.0*t*(1.0-t)*(1.0-t);
t0 = (1.0-t)*(1.0-t)*(1.0-t);
p[0] = t0*x1[0]+t1*x2[0]+t2*x3[0]+t3*x4[0];
p[1] = t0*x1[1]+t1*x2[1]+t2*x3[1]+t3*x4[1];
vv = (p[0]-x)*(p[0]-x) + (p[1]-y)*(p[1]-y);
if (vv < vmin) vmin = vv;
}
return sqrt(vmin);
}